﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace MetaSharp.Transformation.Patterns
{
    class ExactQuantityPattern : Pattern
    {
        public Pattern Pattern { get; private set; }
        public int Quantity { get; private set; }

        public ExactQuantityPattern(Pattern pattern, int quantity)
            : base(PatternKind.ExactQuantity)
        {
            this.Pattern = pattern;
            this.Quantity = quantity;
        }

        public override PatternMatch Compile()
        {
            var p = Pattern.Compile();
            return s => Target(s, p, Quantity);
        }

        private static async Task<IMatch> Target(IScope scope, PatternMatch pattern, int quantity)
        {
            if (quantity < 0)
                throw new ArgumentOutOfRangeException("quantity", "Quantity must be a positive number or 0.");

            var end = scope;
            var matches = new List<object>();
            while (matches.Count != quantity)
            {
                var match = await pattern(end);
                if (!match.Matched)
                    break;

                end = match.End;
                matches.Add(match.Value);
            }

            if (matches.Count == quantity)
                return new Match(
                    matches.ToArray(),
                    scope,
                    end);

            return await Transformation.Match.Fail(scope);
        }
    }
}
